﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.IO;
using System.Text;
using System.Windows.Forms;
using MathNet.Numerics.LinearAlgebra;
using VnSegmenter.Core;

using cit.CopyDetection.DatabaseAccess;
using cit.CopyDetection.Preprocessing;
using cit.CopyDetection.Model;
using cit.CopyDetection.DataObject;

namespace cit.CopyDetection
{
    public partial class frmRegistration : Form
    {
        private List<string> files;
        private List<string> paths;
        private List<Document> registeredDocuments;
        private List<Document> unregisteredDocuments;
        private Registerer registerer;
        private BackgroundWorker registrationWorker;
        private BackgroundWorker unregistrationWorker;

        public frmRegistration()
        {
            InitializeComponent();

            files = new List<string>();
            paths = new List<string>();
            registeredDocuments = new List<Document>();
            unregisteredDocuments = new List<Document>();

            registerer = new Registerer();

            registrationWorker = new BackgroundWorker();
            registrationWorker.DoWork += new DoWorkEventHandler(registrationWorker_DoWork);
            registrationWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(registrationWorker_RunWorkerCompleted);

            unregistrationWorker = new BackgroundWorker();
            unregistrationWorker.DoWork += new DoWorkEventHandler(unregistrationWorker_DoWork);
            unregistrationWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(unregistrationWorker_RunWorkerCompleted);
        }

        private void frmRegisterDocuments_Load(object sender, EventArgs e)
        {
            LoadRegisteredDocuments();
        }

        private void registrationWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            List<Document> documents = (List<Document>)e.Argument;
            RegisterDocuments(documents);
        }

        private void registrationWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
                MessageBox.Show(e.Error.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            else
                MessageBox.Show("Register documents successfully!", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
            this.Cursor = Cursors.Default;
            EnableControls(true);
            registeredDocuments.Clear();
            LoadRegisteredDocuments();
        }

        private void unregistrationWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            List<Document> documents = (List<Document>)e.Argument;
            UnregisterDocuments(documents);
        }

        private void unregistrationWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
                MessageBox.Show(e.Error.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            else
                MessageBox.Show("Unregister documents successfully!", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
            this.Cursor = Cursors.Default;
            EnableControls(true);
            unregisteredDocuments.Clear();
            LoadRegisteredDocuments();
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            OpenFileDialog txtOpenFileDiagalog = new OpenFileDialog();
            txtOpenFileDiagalog.Filter = "txt files | *.txt";
            txtOpenFileDiagalog.RestoreDirectory = true;
            txtOpenFileDiagalog.Multiselect = true;

            if (txtOpenFileDiagalog.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    for (int i = 0; i < txtOpenFileDiagalog.FileNames.Length; i++)
                    {
                        if (!files.Contains(txtOpenFileDiagalog.FileNames[i]))
                        {
                            files.Add(txtOpenFileDiagalog.SafeFileNames[i]);
                            paths.Add(txtOpenFileDiagalog.FileNames[i]);
                            lbxDocuments.Items.Add(txtOpenFileDiagalog.FileNames[i]);
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void btnRegister_Click(object sender, EventArgs e)
        {
            if (lbxDocuments.Items.Count == 0)
            {
                MessageBox.Show("Add file(s) to register.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            for (int i = 0; i < files.Count; i++)
            {
                if (DocumentDataAccess.IsExist(new Document(files[i], paths[i])))
                    MessageBox.Show("File '" + files[i] + "' is already registered.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                else
                    registeredDocuments.Add(new Document(files[i], paths[i]));
            }

            if (registeredDocuments.Count > 0)
            {
                EnableControls(false);
                this.Cursor = Cursors.WaitCursor;
                registrationWorker.RunWorkerAsync(registeredDocuments);
            }
        }

        private void btnRemove_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < lbxDocuments.SelectedIndices.Count; i++)
            {
                int index = lbxDocuments.SelectedIndices[i--];
                files.RemoveAt(index);
                paths.RemoveAt(index);                
                lbxDocuments.Items.RemoveAt(index);
            }
        }

        private void btnUnregister_Click(object sender, EventArgs e)
        {
            int nfiles = lbxRegisteredDocuments.SelectedItems.Count;
            if (nfiles == 0)
            {
                MessageBox.Show("Choose file(s) to unregister.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            DialogResult result = MessageBox.Show("Do you want to unregister chosen file(s)?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            
            if (result == DialogResult.Yes)
            {
                for (int i = 0; i < nfiles; i++)
                {
                    string docLocation = lbxRegisteredDocuments.SelectedItems[i].ToString();
                    Document document = new Document();
                    document.Location = docLocation;
                    document.Name = GetFileName(docLocation);

                    unregisteredDocuments.Add(document);
                }

                EnableControls(false);
                this.Cursor = Cursors.WaitCursor;
                unregistrationWorker.RunWorkerAsync(unregisteredDocuments);
            }
        }

        private void RegisterDocuments(List<Document> documents)
        {
            foreach (Document document in documents)
            {
                string name = document.Name; 
                string desPath = ConfigReader.DocumentPath + name;
                File.Copy(document.Location, desPath, true);
                registerer.RegisterDocument(new Document(name, ConfigReader.DocumentFolder + name));
            }
        }

        private void UnregisterDocuments(List<Document> documents)
        {
            foreach (Document document in documents)
            {
                registerer.UnregisterDocument(document);
                if (File.Exists(document.Location)) File.Delete(document.Location);                 
            }
        }

        private void LoadRegisteredDocuments()
        {
            List<Document> documents = DocumentDataAccess.GetDocuments();

            lbxRegisteredDocuments.BeginUpdate();
            lbxRegisteredDocuments.Items.Clear();
            foreach (Document d in documents)
            {
                lbxRegisteredDocuments.Items.Add(ConfigReader.BasePath + d.Location);
            }
            lbxRegisteredDocuments.EndUpdate();
        }

        private void EnableControls(bool flag)
        {
            foreach (Control ctrl in this.Controls)
            {
                ctrl.Enabled = flag;
            }
        }

        private string GetFileName(string location)
        {
            string[] tokens = location.Split(new char[] { '\\' });
            return tokens[tokens.Length - 1];
        }

        private void lbxRegisteredDocuments_DoubleClick(object sender, EventArgs e)
        {
            if (lbxRegisteredDocuments.SelectedIndices.Count > 0)
            {
                string fileName = (string)lbxRegisteredDocuments.SelectedItems[0];
                frmTextContent contentViewing = new frmTextContent();
                contentViewing.ShowContent(fileName);
            }
        }
    }
}
